package com.infolab.aims.domain.receive;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.FactoryUtils;
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;

import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.hibernate.validator.constraints.NotBlank;


import com.infolab.aims.GlobalConstant;
import com.infolab.aims.common.SpecialMuLineToStringStyle;
import com.infolab.aims.common.SpecialToStringStyle;
import com.infolab.aims.common.bean.AbstractModelBean;
import com.infolab.aims.domain.Department;
import com.infolab.aims.domain.Location;
import com.infolab.aims.domain.Vendor;
import com.infolab.aims.domain.asset.AssetModel;
import com.infolab.aims.domain.purchase.PurchaseOrder;


@Entity
@Table(name="AMTB_DELIVERYORDER")
public class DeliveryOrder extends AbstractModelBean implements Serializable{
	
	
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer deliveryOrderId;
	

	@NotBlank(message="{error.empty}")
	@Column(unique=true)

	private String deliveryOrderCode;
	
	@NotBlank(message="{error.empty}")
	private String deliveryOrderType;
	
	private String deliveryOrderStatus;
	
	@NotNull(message="{error.empty}")
	private Date deliveryOrderDate;
	
	@ManyToOne
	@JoinColumn(name="purchaseOrderId")
	@NotNull(message="{error.empty}")
	private PurchaseOrder purchaseOrder;
	
	@ManyToOne
	@JoinColumn(name="accessDepartmentId")
	private Department accessDepartment;
	
	/**
	 * for new delivery order and repair delivery order, location will be assumed as receiving location
	 * 
	 */
	@ManyToOne
	@JoinColumn(name="locationId")
	private Location location;
	
	
	
	private Date effectiveStartDate;
	
	
	private Date effectiveEndDate;
	
	public Date getEffectiveStartDate() {
		return effectiveStartDate;
	}

	public void setEffectiveStartDate(Date effectiveStartDate) {
		this.effectiveStartDate = effectiveStartDate;
	}

	public Date getEffectiveEndDate() {
		return effectiveEndDate;
	}

	public void setEffectiveEndDate(Date effectiveEndDate) {
		this.effectiveEndDate = effectiveEndDate;
	}





	
	@Transient
	private List<DeliveryOrderComponent> deliveryOrderComponents = LazyList.decorate(new ArrayList(),
		      FactoryUtils.instantiateFactory(DeliveryOrderComponent.class));

	@Transient
	private List<DeliveryOrderEquipment> deliveryOrderEquipments = LazyList.decorate(new ArrayList(),
			  FactoryUtils.instantiateFactory(DeliveryOrderEquipment.class));   

	public Integer getDeliveryOrderId() {
		return deliveryOrderId;
	}

	public void setDeliveryOrderId(Integer deliveryOrderId) {
		this.deliveryOrderId = deliveryOrderId;
	}

	public String getDeliveryOrderCode() {
		return deliveryOrderCode;
	}

	public void setDeliveryOrderCode(String deliveryOrderCode) {
		this.deliveryOrderCode = deliveryOrderCode;
	}

	public String getDeliveryOrderType() {
		return deliveryOrderType;
	}

	public void setDeliveryOrderType(String deliveryOrderType) {
		this.deliveryOrderType = deliveryOrderType;
	}

	public String getDeliveryOrderStatus() {
		return deliveryOrderStatus;
	}

	public void setDeliveryOrderStatus(String deliveryOrderStatus) {
		this.deliveryOrderStatus = deliveryOrderStatus;
	}

	public Date getDeliveryOrderDate() {
		return deliveryOrderDate;
	}

	public void setDeliveryOrderDate(Date deliveryOrderDate) {
		this.deliveryOrderDate = deliveryOrderDate;
	}

	public PurchaseOrder getPurchaseOrder() {
		return purchaseOrder;
	}

	public void setPurchaseOrder(PurchaseOrder purchaseOrder) {
		this.purchaseOrder = purchaseOrder;
	}

	public Department getAccessDepartment() {
		return accessDepartment;
	}

	public void setAccessDepartment(Department accessDepartment) {
		this.accessDepartment = accessDepartment;
	}

	public Location getLocation() {
		return location;
	}

	public void setLocation(Location location) {
		this.location = location;
	}
	

	public String getDeliveryOrderDateToDisplay()
	{
		DateTimeFormatter fmt = DateTimeFormat.forPattern(GlobalConstant.DATE_FORMAT_JAVA);
		
		if(deliveryOrderDate!=null) return new LocalDate(deliveryOrderDate.getTime()).toString(fmt);
				
		return "";
	}
	
	public String getEffectiveStartDateToDisplay()
	{
		DateTimeFormatter fmt = DateTimeFormat.forPattern(GlobalConstant.DATE_FORMAT_JAVA);
		
		if(effectiveStartDate!=null) return new LocalDate(effectiveStartDate.getTime()).toString(fmt);
				
		return "";
	}
	
	public String getEffectiveEndDateToDisplay()
	{
		DateTimeFormatter fmt = DateTimeFormat.forPattern(GlobalConstant.DATE_FORMAT_JAVA);
		
		if(effectiveEndDate!=null) return new LocalDate(effectiveEndDate.getTime()).toString(fmt);
				
		return "";
	}
	
	

	public boolean isRepairDeliveryOrder()
	{
		return StringUtils.equalsIgnoreCase(DELIVERYORDERTYPE_REPAIR, deliveryOrderType);
	}

	public boolean isNewDeliveryOrder()
	{
		return StringUtils.equalsIgnoreCase(DELIVERYORDERTYPE_NEW, deliveryOrderType);
	}
	
	public boolean isEquipmentDeliveryOrder()
	{
		return StringUtils.equalsIgnoreCase(AssetModel.ASSETTYPE_EQUIPMENT, purchaseOrder.getAssetType());
	}
	
	public boolean isComponentDeliveryOrder()
	{
		return StringUtils.equalsIgnoreCase(AssetModel.ASSETTYPE_COMPONENT, purchaseOrder.getAssetType());
	}
	
	
	
	public List<DeliveryOrderComponent> getDeliveryOrderComponents() {
		return deliveryOrderComponents;
	}

	public void setDeliveryOrderComponents(
			List<DeliveryOrderComponent> deliveryOrderComponents) {
		this.deliveryOrderComponents = deliveryOrderComponents;
	}

	public List<DeliveryOrderEquipment> getDeliveryOrderEquipments() {
		return deliveryOrderEquipments;
	}

	public void setDeliveryOrderEquipments(
			List<DeliveryOrderEquipment> deliveryOrderEquipments) {
		this.deliveryOrderEquipments = deliveryOrderEquipments;
	}


	public String getAuditContentHead()
	{
		
		PurchaseOrder po = purchaseOrder;
		Vendor ven = po.getVendor()!=null? po.getVendor():new Vendor();
		Location loc = location!=null? location:new Location();
		
		return new ToStringBuilder(this,SpecialToStringStyle.SPECIAL_STYLE)
			.append("Code",deliveryOrderCode)
			.append("For Purchase Order",po.getPurchaseOrderCode())
			.append("PO date",po.getPurchaseOrderDateToDisplay())
			.append("DO Date",getDeliveryOrderDateToDisplay())
			.append("DO OrderType",deliveryOrderType)
			.append("Vendor", ven.getVendorId() + " " + ven.getVendorName())			
			.append("Asset Type",po.getAssetType())
			.append("Location", loc.getLocationCode() + " " + loc.getLocationName())
			.append("Company Code", po.getCompanyCode()!=null? po.getCompanyCode():"")
			.toString();
	}
	
	public String getAuditContentDetail()
	{
		ToStringBuilder builder = new ToStringBuilder(this,SpecialMuLineToStringStyle.SPECIAL_MULINE_STYLE);
		if(deliveryOrderComponents!=null && CollectionUtils.isNotEmpty(deliveryOrderComponents))
		{
			int i = 0;
			for(DeliveryOrderComponent deliveryOrderComponent : deliveryOrderComponents)
			{
				if(!deliveryOrderComponent.isDeleted()){
					builder.append("Item " + (++i), deliveryOrderComponent.getAuditContentHead());
				}
			}
			String str = builder.toString();
			return StringUtils.substring(str, str.indexOf("[")+1, str.lastIndexOf("]")-1);
		}
		
		else if(deliveryOrderEquipments!=null && CollectionUtils.isNotEmpty(deliveryOrderEquipments))
		{
			int i = 0;
			for(DeliveryOrderEquipment deliveryOrderEquipment : deliveryOrderEquipments)
			{
				if(!deliveryOrderEquipment.isDeleted()){
					builder.append("Item " + (++i), deliveryOrderEquipment.getAuditContentHead());
				}
			}
			String str = builder.toString();
			return StringUtils.substring(str, str.indexOf("[")+1, str.lastIndexOf("]")-1);
		}
		
		return super.getAuditContentDetail();
	}


	public String getAuditCode()
	{
		if(StringUtils.isNotEmpty(deliveryOrderCode)){
			return deliveryOrderCode;
		}
		return super.getAuditCode();
	}


	
	public static final String DELIVERYORDERSTATUS_CLOSED = "CLOSED";
	
	public static final String DELIVERYORDERTYPE_NEW="NEW";
	public static final String DELIVERYORDERTYPE_REPAIR="REPAIR";
	
}
